//
// Created by root on 4/29/17.
//

#include "runner_trans.h"


/**
 * rule
 * */

// {define lex rule {boolean} -> {"<bool> :: ($)"}}
static void test_rule() {
    Statement *s1 = parse("{boolean}");
    Statement *s2 = parse("{\"<bool> :: ($)\"}");
    rule(s1, s2);
    Rule *the_rule = NULL;
    hashmap_get(rules, "boolean", (void**)(&the_rule));
    assert_non_null(the_rule);
    assert_int_equal(the_rule->type, RULE);
}

/**
 * group
 * */

// {define lex group {integer} -> {"(<sign><digit>+) :: (lex-integer $)"}}
static void test_group() {
    Statement *s1 = parse("{integer}");
    Statement *s2 = parse("{\"(<sign><digit>+) :: (lex-integer $)\"}");
    group(s1, s2);
    Rule *the_group = NULL;
    hashmap_get(rules, "integer", (void**)(&the_group));
    assert_non_null(the_group);
    assert_int_equal(the_group->type, GROUP);
}

/**
 * token
 * */

// {define lex token {bool} -> {"#[tf]"}}
static void test_token() {
    Statement *s1 = parse("{bool}");
    Statement *s2 = parse("{\"#[tf]\"}");
    token(s1, s2);
    Rule *the_token = NULL;
    hashmap_get(rules, "bool", (void**)(&the_token));
    assert_non_null(the_token);
    assert_int_equal(the_token->type, TOKEN);
}

/**
 * lex
 * */

// {begin lex {"integer > fraction > decimal > complex"}}
static void test_lex() {
    Statement *s = parse("{\"integer > fraction > decimal > complex\"}");
    lex(s);
    assert_non_null(lexOrders);
    assert_string_equal(lexOrders[0], "integer");
    assert_string_equal(lexOrders[1], "fraction");
    assert_string_equal(lexOrders[2], "decimal");
    assert_string_equal(lexOrders[3], "complex");
    assert_null(lexOrders[4]);
}

/**
 * extract
 * */

static void test_extract_when_type_is_sym() {
    Statement *s = init_sym("abc");
    assert_null(extract(s));
}

static void test_extract_when_type_is_loop() {
    Statement *s = init_loop();
    add_statement(s, "abc", LOOP);
    assert_null(extract(s));
}

static void test_extract_when_type_is_arg() {
    Statement *s = parse("{abc}");
    assert_string_equal(extract(s), "abc");
}

static void test_extract_when_type_is_arg_with_space() {
    Statement *s = parse("{abc def}");
    assert_string_equal(extract(s), "abc def");
}

/**
 * arglist
 * */

static void test_arglist_with_sym() {
    Statement *s = parse("{there is {arg} surround sym {a}, followed by {b}}");
    assert_string_equal(arglist(s), "arg a b");
}

static void test_arglist_without_sym() {
    Statement *s = parse("{{a} {b} {c}}");
    assert_string_equal(arglist(s), "a b c");
}

//loop cannot placed here
static void test_arglist_when_has_loop() {
    Statement *s = parse("{{a} {{b} ...} {c}}");
    assert_string_equal(arglist(s), "a c");
}

/**
 * target
 * */

static void test_target_with_sym() {
    Statement *s = parse("{there is {arg} surround sym {a}, followed by {b}}");
    assert_string_equal(target(s), "{arg} {a} {b}");
}

static void test_target_without_sym() {
    Statement *s = parse("{{a} {b} {c}}");
    assert_string_equal(target(s), "{a} {b} {c}");
}

//loop cannot placed here
static void test_target_when_has_loop() {
    Statement *s = parse("{{a} {{b} ...} {c}}");
    assert_string_equal(target(s), "{a} {c}");
}

/**
 * funcname
 * */

static void test_funcname_none_null() {
    Statement *s = parse("{(sum {x} {y})}");
    assert_string_equal(funcname(s), "sum");
}

static void test_funcname_null() {
    Statement *s = parse("{sum {x} {y}}");
    assert_null(funcname(s));
}

/**
 * loadtemplate
 * */

static void test_loadtemplate() {
    ;
}

/**
 * loadfile
 * */

static void test_extract_string() {
    printf(extract_string("(lex \\\"Symbol\\\" \\\"$\\\")"));
}

int main(int argc, char **argv) {
    const struct CMUnitTest tests[] = {
            cmocka_unit_test(test_rule),
            cmocka_unit_test(test_group),
            cmocka_unit_test(test_token),
            cmocka_unit_test(test_lex),
            cmocka_unit_test(test_extract_when_type_is_sym),
            cmocka_unit_test(test_extract_when_type_is_loop),
            cmocka_unit_test(test_extract_when_type_is_arg),
            cmocka_unit_test(test_extract_when_type_is_arg_with_space),
            cmocka_unit_test(test_arglist_with_sym),
            cmocka_unit_test(test_arglist_without_sym),
            cmocka_unit_test(test_arglist_when_has_loop),
            cmocka_unit_test(test_target_with_sym),
            cmocka_unit_test(test_target_without_sym),
            cmocka_unit_test(test_target_when_has_loop),
            cmocka_unit_test(test_funcname_none_null),
            cmocka_unit_test(test_funcname_null),
            cmocka_unit_test(test_extract_string),
    };
    return cmocka_run_group_tests(tests, setup_translate, teardown_translate);
}
